import os

import requests
import yaml


def get_yamlpath_recursion(directory: str) -> list[str]:
    """
    从指定目录递归加载全部yaml文件的路径

    :param directory: 存放yaml用例的目录
    :return: 全部yaml文件的路径，包括子目录
    """
    yamlpath: list[str] = []
    for root, _, files in os.walk(directory):
        for f in files:
            if f.lower().endswith(('.yaml', '.yml')):
                yamlpath.append(os.path.join(root, f))
    return yamlpath


# 从指定目录加载全部yaml文件的路径
def get_yamlpath(directory: str) -> list[str]:
    """
    从指定目录加载全部yaml文件的路径

    :param directory: 存放yaml用例的目录
    :return: 全部yaml文件的路径，不包括子目录
    """
    yamlpath: list[str] = []
    for f in os.listdir(directory):
        if f.lower().endswith(('.yaml', '.yml')):
            yamlpath.append(os.path.join(directory, f))
    return yamlpath


def load_global_var(file_path: str) -> dict:
    """
    从yaml文件加载全局变量
    """
    if not os.path.isfile(file_path):
        return {}
    with open(file_path, 'r', encoding='utf-8') as file:
        global_var: dict = yaml.safe_load(file)
        for key, value in global_var.items():
            if not isinstance(key, str):
                raise TypeError(f"Global variable key must be str, got {type(key)}")
            if not isinstance(value, (str, bool, int, float)):
                raise TypeError(f"Global variable value must be str/bool/int/float, got {type(value)}")
        return global_var


def safe_request_body(request: requests.PreparedRequest, limit=1024) -> str | None:
    """
    安全获取字符串描述的request_body
    """
    body = request.body
    body_type = type(body)
    if body_type == bytes:
        return f"<binary content: {len(body)} bytes>"
    if body_type == str:
        if len(body) > limit:
            return body[:limit] + f"... [truncated {len(body) - limit} chars]"
        return body
    return None


def safe_response_body(response: requests.Response, limit=1024):
    """
    安全获取字符串描述的response_body
    """
    content_type = response.headers.get('Content-Type', '').lower()
    # 判断是否为常见文本类型
    if any(ct in content_type for ct in ('text', 'json', 'xml', 'javascript')):
        try:
            text = response.text
            if len(text) > limit:
                return text[:limit] + f"... [truncated {len(text) - limit} chars]"
            return text
        except UnicodeDecodeError:
            return f"<binary content: {len(response.content)} bytes>"
    else:
        # 非文本类型，直接返回提示
        return f"<binary content: {len(response.content)} bytes>"
